{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.0.4\n",
      "1.1.0\n"
     ]
    }
   ],
   "source": [
    "import keras\n",
    "import tensorflow as tf\n",
    "print(keras.__version__)\n",
    "print(tf.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import os\n",
    "from os.path import join\n",
    "import json\n",
    "import random\n",
    "import itertools\n",
    "import re\n",
    "import datetime\n",
    "import cairocffi as cairo\n",
    "import editdistance\n",
    "import numpy as np\n",
    "from scipy import ndimage\n",
    "import pylab\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.gridspec as gridspec\n",
    "from keras import backend as K\n",
    "from keras.layers.convolutional import Conv2D, MaxPooling2D\n",
    "from keras.layers import Input, Dense, Activation\n",
    "from keras.layers import Reshape, Lambda\n",
    "from keras.layers.merge import add, concatenate\n",
    "from keras.models import Model, load_model\n",
    "from keras.layers.recurrent import GRU\n",
    "from keras.optimizers import SGD\n",
    "from keras.utils.data_utils import get_file\n",
    "from keras.preprocessing import image\n",
    "import keras.callbacks\n",
    "import cv2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "sess = tf.Session()\n",
    "K.set_session(sess)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "channels_last\n"
     ]
    }
   ],
   "source": [
    "print(K.image_data_format())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Plate lengths: Counter({8: 10788})\n",
      "Plate lengths: Counter({8: 10788})\n",
      "22 22 22\n",
      "0 1 2 3 4 5 6 7 8 9 A B C E H K M O P T X Y\n"
     ]
    }
   ],
   "source": [
    "from collections import Counter\n",
    "def get_counter(dirpath):\n",
    "    ann_dirpath = join(dirpath, 'ann')\n",
    "    letters = ''\n",
    "    lens = []\n",
    "    for filename in os.listdir(ann_dirpath):\n",
    "        json_filepath = join(ann_dirpath, filename)\n",
    "        description = json.load(open(json_filepath, 'r'))['description']\n",
    "        lens.append(len(description))\n",
    "        letters += description\n",
    "    print('Plate lengths:', Counter(lens))\n",
    "    return Counter(letters)\n",
    "c_train = get_counter('/data/001/train/')\n",
    "c_val = get_counter('/data/001/train/')\n",
    "letters_train = set(c_train.keys())\n",
    "letters_val = set(c_val.keys())\n",
    "print(len(letters_train), len(letters_val), len(letters_val & letters_train))\n",
    "letters = sorted(list(letters_train))\n",
    "print(' '.join(letters))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "OUTPUT_DIR = 'image_ocr'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "random.seed(55)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def text_to_labels(text):\n",
    "    return list(map(lambda x: letters.index(x), text))\n",
    "\n",
    "def is_valid_str(s):\n",
    "    for ch in s:\n",
    "        if not ch in letters:\n",
    "            return False\n",
    "    return True\n",
    "\n",
    "class TextImageGenerator:\n",
    "    \n",
    "    def __init__(self, \n",
    "                 dirpath, \n",
    "                 img_w, img_h, \n",
    "                 batch_size, \n",
    "                 downsample_factor,\n",
    "                 max_text_len=8):\n",
    "        \n",
    "        self.img_h = img_h\n",
    "        self.img_w = img_w\n",
    "        self.batch_size = batch_size\n",
    "        self.max_text_len = max_text_len\n",
    "        self.downsample_factor = downsample_factor\n",
    "        \n",
    "        img_dirpath = join(dirpath, 'img')\n",
    "        ann_dirpath = join(dirpath, 'ann')\n",
    "        self.samples = []\n",
    "        for filename in os.listdir(img_dirpath):\n",
    "            name, ext = os.path.splitext(filename)\n",
    "            if ext == '.png':\n",
    "                img_filepath = join(img_dirpath, filename)\n",
    "                json_filepath = join(ann_dirpath, name + '.json')\n",
    "                description = json.load(open(json_filepath, 'r'))['description']\n",
    "                if is_valid_str(description):\n",
    "                    self.samples.append([img_filepath, description])\n",
    "        \n",
    "        self.n = len(self.samples)\n",
    "        self.indexes = list(range(self.n))\n",
    "        self.cur_index = 0\n",
    "        \n",
    "    def build_data(self):\n",
    "        self.imgs = np.zeros((self.n, self.img_h, self.img_w))\n",
    "        self.texts = []\n",
    "        for i, (img_filepath, text) in enumerate(self.samples):\n",
    "            img = cv2.imread(img_filepath)\n",
    "            img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
    "            img = cv2.resize(img, (self.img_w, self.img_h))\n",
    "            img = img.astype(np.float32)\n",
    "            img /= 255\n",
    "            # width and height are backwards from typical Keras convention\n",
    "            # because width is the time dimension when it gets fed into the RNN\n",
    "            self.imgs[i, :, :] = img\n",
    "            self.texts.append(text)\n",
    "        \n",
    "    def get_output_size(self):\n",
    "        return len(letters) + 1\n",
    "    \n",
    "    def next_sample(self):\n",
    "        self.cur_index += 1\n",
    "        if self.cur_index >= self.n:\n",
    "            self.cur_index = 0\n",
    "            random.shuffle(self.indexes)\n",
    "        return self.imgs[self.indexes[self.cur_index]], self.texts[self.indexes[self.cur_index]]\n",
    "    \n",
    "    def next_batch(self):\n",
    "        while True:\n",
    "            # width and height are backwards from typical Keras convention\n",
    "            # because width is the time dimension when it gets fed into the RNN\n",
    "            if K.image_data_format() == 'channels_first':\n",
    "                X_data = np.ones([self.batch_size, 1, self.img_w, self.img_h])\n",
    "            else:\n",
    "                X_data = np.ones([self.batch_size, self.img_w, self.img_h, 1])\n",
    "            Y_data = np.ones([self.batch_size, self.max_text_len])\n",
    "            input_length = np.ones((self.batch_size, 1)) * (self.img_w // self.downsample_factor - 2)\n",
    "            label_length = np.zeros((self.batch_size, 1))\n",
    "            source_str = []\n",
    "                                   \n",
    "            for i in range(self.batch_size):\n",
    "                img, text = self.next_sample()\n",
    "                img = img.T\n",
    "                if K.image_data_format() == 'channels_first':\n",
    "                    img = np.expand_dims(img, 0)\n",
    "                else:\n",
    "                    img = np.expand_dims(img, -1)\n",
    "                X_data[i] = img\n",
    "                Y_data[i] = text_to_labels(text)\n",
    "                source_str.append(text)\n",
    "                label_length[i] = len(text)\n",
    "                \n",
    "            inputs = {\n",
    "                'the_input': X_data,\n",
    "                'the_labels': Y_data,\n",
    "                'input_length': input_length,\n",
    "                'label_length': label_length,\n",
    "                #'source_str': source_str\n",
    "            }\n",
    "            outputs = {'ctc': np.zeros([self.batch_size])}\n",
    "            yield (inputs, outputs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "tiger = TextImageGenerator('/data/001/val', 128, 64, 8, 4)\n",
    "tiger.build_data()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f10a099edd8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 19.   5.   4.   3.  21.  15.   9.   6.]\n",
      "[ 30.]\n",
      "[ 8.]\n"
     ]
    }
   ],
   "source": [
    "for inp, out in tiger.next_batch():\n",
    "    if K.image_data_format() == 'channels_first':\n",
    "        img = inp['the_input'][0, 0, :, :]\n",
    "    else:\n",
    "        img = inp['the_input'][0, :, :, 0]\n",
    "    plt.imshow(img)\n",
    "    plt.show()\n",
    "    print(inp['the_labels'][0])\n",
    "    print(inp['input_length'][0])\n",
    "    print(inp['label_length'][0])\n",
    "    #print(inp['source_str'][0])\n",
    "    break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def ctc_lambda_func(args):\n",
    "    y_pred, labels, input_length, label_length = args\n",
    "    # the 2 is critical here since the first couple outputs of the RNN\n",
    "    # tend to be garbage:\n",
    "    y_pred = y_pred[:, 2:, :]\n",
    "    return K.ctc_batch_cost(labels, y_pred, input_length, label_length)\n",
    "\n",
    "\n",
    "def train(run_name, start_epoch, stop_epoch, img_w, load=False):\n",
    "    # Input Parameters\n",
    "    img_h = 64\n",
    "\n",
    "    # Network parameters\n",
    "    conv_filters = 16\n",
    "    kernel_size = (3, 3)\n",
    "    pool_size = 2\n",
    "    time_dense_size = 32\n",
    "    rnn_size = 512\n",
    "\n",
    "    if K.image_data_format() == 'channels_first':\n",
    "        input_shape = (1, img_w, img_h)\n",
    "    else:\n",
    "        input_shape = (img_w, img_h, 1)\n",
    "        \n",
    "    batch_size = 32\n",
    "    downsample_factor = pool_size ** 2\n",
    "    tiger_train = TextImageGenerator('/data/001/train', img_w, img_h, batch_size, downsample_factor)\n",
    "    tiger_train.build_data()\n",
    "    tiger_val = TextImageGenerator('/data/001/val', img_w, img_h, batch_size, downsample_factor)\n",
    "    tiger_val.build_data()\n",
    "\n",
    "    act = 'relu'\n",
    "    input_data = Input(name='the_input', shape=input_shape, dtype='float32')\n",
    "    inner = Conv2D(conv_filters, kernel_size, padding='same',\n",
    "                   activation=act, kernel_initializer='he_normal',\n",
    "                   name='conv1')(input_data)\n",
    "    inner = MaxPooling2D(pool_size=(pool_size, pool_size), name='max1')(inner)\n",
    "    inner = Conv2D(conv_filters, kernel_size, padding='same',\n",
    "                   activation=act, kernel_initializer='he_normal',\n",
    "                   name='conv2')(inner)\n",
    "    inner = MaxPooling2D(pool_size=(pool_size, pool_size), name='max2')(inner)\n",
    "\n",
    "    conv_to_rnn_dims = (img_w // (pool_size ** 2), (img_h // (pool_size ** 2)) * conv_filters)\n",
    "    inner = Reshape(target_shape=conv_to_rnn_dims, name='reshape')(inner)\n",
    "\n",
    "    # cuts down input size going into RNN:\n",
    "    inner = Dense(time_dense_size, activation=act, name='dense1')(inner)\n",
    "\n",
    "    # Two layers of bidirecitonal GRUs\n",
    "    # GRU seems to work as well, if not better than LSTM:\n",
    "    gru_1 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru1')(inner)\n",
    "    gru_1b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru1_b')(inner)\n",
    "    gru1_merged = add([gru_1, gru_1b])\n",
    "    gru_2 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru2')(gru1_merged)\n",
    "    gru_2b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru2_b')(gru1_merged)\n",
    "\n",
    "    # transforms RNN output to character activations:\n",
    "    inner = Dense(tiger_train.get_output_size(), kernel_initializer='he_normal',\n",
    "                  name='dense2')(concatenate([gru_2, gru_2b]))\n",
    "    y_pred = Activation('softmax', name='softmax')(inner)\n",
    "    Model(inputs=input_data, outputs=y_pred).summary()\n",
    "\n",
    "    labels = Input(name='the_labels', shape=[tiger_train.max_text_len], dtype='float32')\n",
    "    input_length = Input(name='input_length', shape=[1], dtype='int64')\n",
    "    label_length = Input(name='label_length', shape=[1], dtype='int64')\n",
    "    # Keras doesn't currently support loss funcs with extra parameters\n",
    "    # so CTC loss is implemented in a lambda layer\n",
    "    loss_out = Lambda(ctc_lambda_func, output_shape=(1,), name='ctc')([y_pred, labels, input_length, label_length])\n",
    "\n",
    "    # clipnorm seems to speeds up convergence\n",
    "    sgd = SGD(lr=0.02, decay=1e-6, momentum=0.9, nesterov=True, clipnorm=5)\n",
    "\n",
    "    if load:\n",
    "        model = load_model('./tmp_model.h5', compile=False)\n",
    "    else:\n",
    "        model = Model(inputs=[input_data, labels, input_length, label_length], outputs=loss_out)\n",
    "\n",
    "    # the loss calc occurs elsewhere, so use a dummy lambda func for the loss\n",
    "    model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer=sgd)\n",
    "    \n",
    "    if not load:\n",
    "        if start_epoch > 0:\n",
    "            weight_file = os.path.join(OUTPUT_DIR, os.path.join(run_name, 'weights%02d.h5' % (start_epoch - 1)))\n",
    "            model.load_weights(weight_file)\n",
    "        # captures output of softmax so we can decode the output during visualization\n",
    "        test_func = K.function([input_data], [y_pred])\n",
    "\n",
    "        model.fit_generator(generator=tiger_train.next_batch(), \n",
    "                            steps_per_epoch=tiger_train.n,\n",
    "                            epochs=stop_epoch, \n",
    "                            validation_data=tiger_val.next_batch(), \n",
    "                            validation_steps=tiger_val.n,\n",
    "                            initial_epoch=start_epoch)\n",
    "\n",
    "    return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "____________________________________________________________________________________________________\n",
      "Layer (type)                     Output Shape          Param #     Connected to                     \n",
      "====================================================================================================\n",
      "the_input (InputLayer)           (None, 128, 64, 1)    0                                            \n",
      "____________________________________________________________________________________________________\n",
      "conv1 (Conv2D)                   (None, 128, 64, 16)   160         the_input[0][0]                  \n",
      "____________________________________________________________________________________________________\n",
      "max1 (MaxPooling2D)              (None, 64, 32, 16)    0           conv1[0][0]                      \n",
      "____________________________________________________________________________________________________\n",
      "conv2 (Conv2D)                   (None, 64, 32, 16)    2320        max1[0][0]                       \n",
      "____________________________________________________________________________________________________\n",
      "max2 (MaxPooling2D)              (None, 32, 16, 16)    0           conv2[0][0]                      \n",
      "____________________________________________________________________________________________________\n",
      "reshape (Reshape)                (None, 32, 256)       0           max2[0][0]                       \n",
      "____________________________________________________________________________________________________\n",
      "dense1 (Dense)                   (None, 32, 32)        8224        reshape[0][0]                    \n",
      "____________________________________________________________________________________________________\n",
      "gru1 (GRU)                       (None, 32, 512)       837120      dense1[0][0]                     \n",
      "____________________________________________________________________________________________________\n",
      "gru1_b (GRU)                     (None, 32, 512)       837120      dense1[0][0]                     \n",
      "____________________________________________________________________________________________________\n",
      "add_1 (Add)                      (None, 32, 512)       0           gru1[0][0]                       \n",
      "                                                                   gru1_b[0][0]                     \n",
      "____________________________________________________________________________________________________\n",
      "gru2 (GRU)                       (None, 32, 512)       1574400     add_1[0][0]                      \n",
      "____________________________________________________________________________________________________\n",
      "gru2_b (GRU)                     (None, 32, 512)       1574400     add_1[0][0]                      \n",
      "____________________________________________________________________________________________________\n",
      "concatenate_1 (Concatenate)      (None, 32, 1024)      0           gru2[0][0]                       \n",
      "                                                                   gru2_b[0][0]                     \n",
      "____________________________________________________________________________________________________\n",
      "dense2 (Dense)                   (None, 32, 23)        23575       concatenate_1[0][0]              \n",
      "____________________________________________________________________________________________________\n",
      "softmax (Activation)             (None, 32, 23)        0           dense2[0][0]                     \n",
      "====================================================================================================\n",
      "Total params: 4,857,319\n",
      "Trainable params: 4,857,319\n",
      "Non-trainable params: 0\n",
      "____________________________________________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "run_name = datetime.datetime.now().strftime('%Y:%m:%d:%H:%M:%S')\n",
    "#model = train(run_name, 0, 1, 128)\n",
    "model = train(run_name, 0, 1, 128, load=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "net_inp = model.get_layer(name='the_input').input\n",
    "net_out = model.get_layer(name='softmax').output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# For a real OCR application, this should be beam search with a dictionary\n",
    "# and language model.  For this example, best path is sufficient.\n",
    "\n",
    "def decode_batch(out):\n",
    "    ret = []\n",
    "    for j in range(out.shape[0]):\n",
    "        out_best = list(np.argmax(out[j, 2:], 1))\n",
    "        out_best = [k for k, g in itertools.groupby(out_best)]\n",
    "        outstr = ''\n",
    "        for c in out_best:\n",
    "            if c < len(letters):\n",
    "                outstr += letters[c]\n",
    "        ret.append(outstr)\n",
    "    return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'M180OT07'"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "texts[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pred: T006PK01\n",
      "True: T006PK01\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f105cd052e8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for inp_value, _ in tiger.next_batch():\n",
    "    bs = inp_value['the_input'].shape[0]\n",
    "    X_data = inp_value['the_input']\n",
    "    net_out_value = sess.run(net_out, feed_dict={net_inp:X_data})\n",
    "    pred_texts = decode_batch(net_out_value)\n",
    "    labels = inp_value['the_labels']\n",
    "    texts = []\n",
    "    for label in labels:\n",
    "        text = ''.join(list(map(lambda x: letters[int(x)], label)))\n",
    "        texts.append(text)\n",
    "    \n",
    "    for i in range(bs):\n",
    "        fig = plt.figure(figsize=(5, 5))\n",
    "        outer = gridspec.GridSpec(2, 1, wspace=10, hspace=0.05)\n",
    "        ax1 = plt.Subplot(fig, outer[0])\n",
    "        fig.add_subplot(ax1)\n",
    "        ax2 = plt.Subplot(fig, outer[1])\n",
    "        fig.add_subplot(ax2)\n",
    "        print('Pred: %s\\nTrue: %s' % (pred_texts[i], texts[i]))\n",
    "        img = X_data[i][:, :, 0].T\n",
    "        ax1.set_label('Img')\n",
    "        ax1.imshow(img)\n",
    "        ax1.set_xticks([])\n",
    "        ax1.set_yticks([])\n",
    "        ax2.imshow(net_out_value[i].T, cmap='binary', interpolation='nearest')\n",
    "        ax2.set_yticks(list(range(len(letters) + 1)))\n",
    "        ax2.set_yticklabels(letters + ['blank'])\n",
    "        ax2.grid(False)\n",
    "        for h in np.arange(-0.5, len(letters) + 1 + 0.5, 1):\n",
    "            ax2.axhline(h, linestyle='-', color='k', alpha=0.5, linewidth=1)\n",
    "        \n",
    "        #ax.axvline(x, linestyle='--', color='k')\n",
    "        plt.show()\n",
    "        break\n",
    "    break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
